package abstractfactory.example;

import java.util.ResourceBundle;

/**抽象工厂好处：
 * 1.便于交换产品系列，由于具体工厂类IFactory iFactory = new SqlserverFactory()只需要初始化一次，只需要改变具体工厂就可以使用不同的产品配置
 * 2.让具体的创建实例过程与客户端分离，client通过抽象接口操纵实例，具体的产品被隐藏
 *
 * 抽象工厂存在问题：
 * 如果需要增加一条产品线需要增加IProject、SqlServerProject、OracleProject，还需要更改IFactory、OracleFactory、SqlserverFactory
 * 而且每一个类的开始都需要声明IFactory iFactory = new SqlserverFactory()
 * 如果需要更换数据库访问，则必须修改每一处声明的地方
 *
 * 用简单工厂改进抽象工厂
 * 改造后，客户端完全不需要知道产品类型，实现了解耦，
 * 但如果加入mysql类型，则需要在DataAccess每一个方法中的switch中增加一个case分支
 *
 * 再次优化：使用反射加配置文件完全解耦
 * 可以去除掉代码中switch或者if-else带来的耦合
 *
 * @author Chen Guang
 * @date 2019/4/11 0011 下午 16:57
 */
public class DataAccess {

    private static final String db = "sqlserver";

    private static String dbName;

    static {
        //读取配置文件赋值
        ResourceBundle resource = ResourceBundle.getBundle("abstractfactory/example/config/globals");
        dbName = resource.getString("abstractfactory.factory.type");
    }

    public static IUser createUser(){
        IUser iUser = null;
        switch (db){
            case "sqlserver":
                iUser = new SqlServerUser();
                break;
            case "oracle":
                iUser = new OracleUser();
                break;
            default:
                //do nothing
        }
        return iUser;
    }

    public static IDepartment createDepartment(){
        IDepartment iDepartment = null;
        switch (db){
            case "sqlserver":
                iDepartment = new SqlServerDepartment();
                break;
            case "oracle":
                iDepartment = new OracleDepartment();
                break;
            default:
                //do nothing
        }
        return iDepartment;
    }

    public static IUser createUserByReflection() throws Exception{
        return (IUser) Class.forName("abstractfactory.example." + dbName + "User").newInstance();
    }

    public static IDepartment createDepartmentByReflection() throws Exception{
        return (IDepartment)Class.forName("abstractfactory.example." + dbName + "Department").newInstance();
    }
}
